﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Runtime.CompilerServices;
using AccesoDatos.DAO;
using AccesoDatos.DTO;
using System.Collections.Generic;
using AccesoDatos.DAO.Base;
using AccesoDatos.DTO.Base;
using System.IO;
using System.Drawing;

namespace AccesoDatos.DAO
{
    /// <summary>
    /// Descripcion breve de PersonaDAO
    /// </summary>
    public class PersonaDAO: BaseDAO, IDAO
    {
        #region Singleton

        private static PersonaDAO instance;

        private PersonaDAO()
        {
            //Vacio
        }

        /// <summary>
        /// Devuelve una instancia de PersonaDTO
        /// </summary>
        /// <returns>instancia de PersonaDAODTO</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static PersonaDAO GetInstance()
        {
            if (instance == null)
            {
                instance = new PersonaDAO();
            }

            return instance;
        }

        #endregion
 
        #region Miembros de IDAO

        /// <summary>
        /// Metodo que inserta un nuevo registro en la base de datos
        /// </summary>
        /// <param name="dto">Objeto de tipo IDTO que contiene todos los parametros a insertar</param>
        public void Insert(IDTO dto)
        {
            PersonaDTO filtro = new PersonaDTO();
            filtro = (PersonaDTO)dto;
            try
            {
                string sql = "spu_PersonaDAO_Insert";
                SqlCommand cmd = new SqlCommand(sql, this.ConexionIntegra);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@CoPersona", GetSqlValue(filtro.CoPersona));
              
                cmd.Parameters.AddWithValue("@Aficiones", GetSqlValue(filtro.Aficiones));
                cmd.Parameters.AddWithValue("@Frase", GetSqlValue(filtro.Frase));
                cmd.Parameters.AddWithValue("@Propio", GetSqlValue(filtro.Propio));
                cmd.Parameters.AddWithValue("@Nick", GetSqlValue(filtro.UltimaConexion));
                cmd.Parameters.AddWithValue("@Imagen", filtro.Imagen);
                cmd.Parameters.AddWithValue("@UltimaConexion", GetSqlValue(filtro.UltimaConexion));
                cmd.Parameters.AddWithValue("@Userhash", GetSqlValue(filtro.Userhash));
                cmd.Parameters.AddWithValue("@Nombre", GetSqlValue(filtro.Nombre));
                cmd.Parameters.AddWithValue("@Apellido1", GetSqlValue(filtro.Apellido1));
                cmd.Parameters.AddWithValue("@Apellido2", GetSqlValue(filtro.Apellido2));
                cmd.Parameters.AddWithValue("@Email", GetSqlValue(filtro.Email));
                cmd.Parameters.AddWithValue("@FechaNacimiento", GetSqlValue(filtro.FechaNacimiento));
                cmd.Parameters.AddWithValue("@Dni", GetSqlValue(filtro.Dni));
                cmd.Parameters.AddWithValue("@EsAdministrador", GetSqlValue(filtro.EsAdministrador));
                cmd.Parameters.AddWithValue("@NombreImagen", GetSqlValue(filtro.NombreImagen));

                cmd.ExecuteNonQuery();
            }
            catch (SqlException ex)
            {
                throw new DAOException(GetErrorSqlPersonalizado(ex));
            }
            catch (Exception ex)
            {
                throw new DAOException(ex);
            }
        }

        /// <summary>
        /// Metodo que elimina un registro de la base de datos
        /// </summary>
        /// <param name="dto">Objeto de tipo IDTO que elimina un registro en la base de datos</param>
        public void Delete(IDTO dto)
        {
            PersonaDTO filtro = new PersonaDTO();
            filtro = (PersonaDTO)dto;
            try
            {
                string sql = "spu_PersonaDAO_Delete";
                SqlCommand cmd = new SqlCommand(sql, this.ConexionIntegra);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@CoPersona", GetSqlValue(filtro.CoPersona));
                cmd.ExecuteNonQuery();
            }
            catch (SqlException ex)
            {
                throw new DAOException(GetErrorSqlPersonalizado(ex));
            }
            catch (Exception ex)
            {
                throw new DAOException(ex);
            }

        }

        /// <summary>
        /// Metodo que actualiza un determinado registro de la base de datos
        /// </summary>
        /// <param name="dto">Objeto de tipo IDTO que contiene todos los parametros a actualizar</param>
        public void Update(IDTO dto)
        {
            PersonaDTO filtro = new PersonaDTO();
            filtro = (PersonaDTO)dto;
            try
            {
                string sql = "spu_PersonaDTO_Update";
                SqlCommand cmd = new SqlCommand(sql, this.ConexionIntegra);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@CoPersona", GetSqlValue(filtro.CoPersona));

                cmd.Parameters.AddWithValue("@Aficiones", GetSqlValue(filtro.Aficiones));
                cmd.Parameters.AddWithValue("@Frase", GetSqlValue(filtro.Frase));
                cmd.Parameters.AddWithValue("@Propio", GetSqlValue(filtro.Propio));
                cmd.Parameters.AddWithValue("@Nick", GetSqlValue(filtro.UltimaConexion));
                cmd.Parameters.AddWithValue("@Imagen", filtro.Imagen);
                cmd.Parameters.AddWithValue("@UltimaConexion", GetSqlValue(filtro.UltimaConexion));
                cmd.Parameters.AddWithValue("@Userhash", GetSqlValue(filtro.Userhash));
                cmd.Parameters.AddWithValue("@Nombre", GetSqlValue(filtro.Nombre));
                cmd.Parameters.AddWithValue("@Apellido1", GetSqlValue(filtro.Apellido1));
                cmd.Parameters.AddWithValue("@Apellido2", GetSqlValue(filtro.Apellido2));
                cmd.Parameters.AddWithValue("@Email", GetSqlValue(filtro.Email));
                cmd.Parameters.AddWithValue("@FechaNacimiento", GetSqlValue(filtro.FechaNacimiento));
                cmd.Parameters.AddWithValue("@Dni", GetSqlValue(filtro.Dni));
                cmd.Parameters.AddWithValue("@NombreImagen", GetSqlValue(filtro.NombreImagen));

                cmd.ExecuteNonQuery();
            }
            catch (SqlException ex)
            {
                throw new DAOException(GetErrorSqlPersonalizado(ex));
            }
            catch (Exception ex)
            {
                throw new DAOException(ex);
            }
        }
       
        /// <summary>
        /// Funcion que devuelve una lista de Personas filtradas por una persona
        /// </summary>
        /// <param name="dto">Objeto de tipo IDTO que contiene todos los parametros por los que se filtrara la busqueda</param>
        /// <returns>Lista de objetos con todo relleno</returns>
        public List<IDTO> Get(IDTO dto)
        {
            PersonaDTO filtro = new PersonaDTO();
            filtro = (PersonaDTO)dto;
            try
            {
                string sql = @"spu_PersonaDAO_GetPersonas";
                List<IDTO> lista = new List<IDTO>();

                SqlCommand cmd = new SqlCommand(sql, this.ConexionIntegra);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@CoPersona", GetSqlValue(filtro.CoPersona));
                cmd.Parameters.AddWithValue("@Aficiones", GetSqlValue(filtro.Aficiones));
                cmd.Parameters.AddWithValue("@Frase", GetSqlValue(filtro.Frase));
                cmd.Parameters.AddWithValue("@Propio", GetSqlValue(filtro.Propio));               
                cmd.Parameters.AddWithValue("@CoNivel", GetSqlValue(filtro.CoNivel));
                cmd.Parameters.AddWithValue("@Nick", GetSqlValue(filtro.Nick));
                cmd.Parameters.AddWithValue("@UltimaConexion", GetSqlValue(filtro.UltimaConexion));
                cmd.Parameters.AddWithValue("@Userhash", GetSqlValue(filtro.Userhash));
                cmd.Parameters.AddWithValue("@Apellido1", GetSqlValue(filtro.Apellido1));
                cmd.Parameters.AddWithValue("@Apellido2", GetSqlValue(filtro.Apellido2));
                cmd.Parameters.AddWithValue("@Nombre", GetSqlValue(filtro.Nombre));
                cmd.Parameters.AddWithValue("@Email", GetSqlValue(filtro.Email));
                cmd.Parameters.AddWithValue("@FechaNacimiento", GetSqlValue(filtro.FechaNacimiento));
                cmd.Parameters.AddWithValue("@Dni", GetSqlValue(filtro.Dni));
                cmd.Parameters.AddWithValue("@CoProfesor", GetSqlValue(filtro.CoProfesor));
                cmd.Parameters.AddWithValue("@EsAdministrador", GetSqlValue(filtro.EsAdministrador));
                cmd.Parameters.AddWithValue("@NombreImagen", GetSqlValue(filtro.NombreImagen));
                cmd.Parameters.AddWithValue("@CoAlumno", GetSqlValue(filtro.CoAlumno));
                
                using (SqlDataReader dr = cmd.ExecuteReader())
                {
                    while (dr.Read())
                    {
                        PersonaDTO persona = new PersonaDTO();
                        persona = RellenaBean(dr);
                        lista.Add(persona);
                    }
                }
                return lista;
            }
            catch (Exception ex)
            {
                throw new DAOException(ex);
            }
        }

        #endregion

        #region Metodos privados

        /// <summary>
        /// Funcion que rellena el bean con los valores obtenidos en DataReader
        /// </summary>
        /// <param name="dr">DataReader que contiene todos los valores directos de la base de datos</param>
        /// <returns>DTO Relleno con los valores obtenidos</returns>
        private PersonaDTO RellenaBean(SqlDataReader dr)
        {
            PersonaDTO bean = new PersonaDTO();
            bean.CoPersona = this.GetNullableIntFromDataReader(dr, "CO_PERSONA");
            bean.Aficiones = this.GetStringFromDataReader(dr, "AFICIONES");
            bean.Frase = this.GetStringFromDataReader(dr, "FRASE");
            bean.Propio = this.GetStringFromDataReader(dr, "PROPIO");
            bean.CoNivel = this.GetNullableIntFromDataReader(dr, "CO_NIVEL");
            bean.Nick = this.GetStringFromDataReader(dr, "NICK");
            bean.UltimaConexion = this.GetNullableDateTimeFromDataReader(dr, "ULTIMA_CONEXION");
               if (dr["IMAGEN"].ToString()!=String.Empty)
            {

                bean.Imagen = this.GetImageFromDataReader(dr, "IMAGEN");
            }
            bean.Userhash = this.GetStringFromDataReader(dr, "USERHASH");
            bean.Nombre = this.GetStringFromDataReader(dr, "NOMBRE");
            bean.Apellido1 = this.GetStringFromDataReader(dr, "APELLIDO1");
            bean.Apellido2 = this.GetStringFromDataReader(dr, "APELLIDO2");
            bean.Email = this.GetStringFromDataReader(dr, "EMAIL");
            bean.FechaNacimiento = this.GetNullableDateTimeFromDataReader(dr, "FECHA_NACIMIENTO");
            bean.Dni = this.GetStringFromDataReader(dr, "DNI");
            bean.CoProfesor = this.GetNullableIntFromDataReader(dr, "CO_PROFESOR");
            bean.EsAdministrador = this.GetNullableIntFromDataReader(dr, "ESADMINISTRADOR");
            bean.NombreImagen = this.GetStringFromDataReader(dr, "NOMBREIMAGEN");
            bean.CoAlumno = this.GetNullableIntFromDataReader(dr, "CO_ALUMNO");

            return bean;
        }
        
        #endregion
    }
}